package com.msda.service.room.Impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.msda.exception.database.DatabaseOperationException;
import com.msda.mapper.*;
import com.msda.pojo.dto.PageDTO;
import com.msda.pojo.dto.order.AuditCancellationDTO;
import com.msda.pojo.dto.order.AuditReservationDTO;
import com.msda.pojo.entity.order.Cancellation;
import com.msda.pojo.entity.order.Order;
import com.msda.pojo.entity.order.Reservation;
import com.msda.pojo.entity.requirement.NoticeMessage;
import com.msda.pojo.entity.room.MeetingRoom;
import com.msda.pojo.entity.staff.Customer;
import com.msda.pojo.entity.staff.User;
import com.msda.pojo.vo.ReservationVO;
import com.msda.rabbitmq.DelayMessageProcessor;
import com.msda.rabbitmq.MultiDelayMessage;
import com.msda.service.room.OrderService;
import com.msda.service.room.RoomService;
import com.msda.service.staff.UserService;
import com.msda.utils.AllFieldsNotNull;
import com.msda.utils.MessageResult;
import com.msda.utils.SnowFlakeID;
import org.springframework.amqp.AmqpException;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;

import static com.msda.constant.MqConstant.*;

@Service
@Transactional
public class OrderServiceImpl implements OrderService {

    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private RabbitTemplate rabbitTemplate;
    @Autowired
    private ReservationMapper reservationMapper;
    @Autowired
    private CancellationMapper cancellationMapper;
    @Autowired
    private RoomService meetingRoomService;
    @Autowired
    private NoticeMessageMapper noticeMessageMapper;
    @Autowired
    private UserService userService;
    @Autowired
    private MeetingRoomMapper meetingRoomMapper;


    //下面业务待上锁
    @Override
    public String submitOrder(Order order) {
        order.setId(SnowFlakeID.getSnowflakeId());
        order.setPaymentStatus("unpaid");
        order.setCreatedTime(System.currentTimeMillis());
        orderMapper.insert(order);
        List<Long> delayList = new ArrayList<>();
        for(int i = 0;i < 15;i++){
            delayList.add(120000L);
        }
        CorrelationData correlationData = new CorrelationData(order.getId());
        try {
            MultiDelayMessage<String> msg = new MultiDelayMessage<>(order.getId(),delayList);
            rabbitTemplate.convertAndSend(DELAY_EXCHANGE,DELAY_ORDER_ROUTINE_KEY,msg,
                    new DelayMessageProcessor(msg.removeNextDelay().intValue()),correlationData);
        } catch (AmqpException e) {
            throw new RuntimeException(e);
        }
        meetingRoomService.lockRoom(order.getRoomId());
        return order.getId();
    }

    @Override
    public Order getOrderById(String orderId) {
        Order order = orderMapper.selectById(orderId);
        return order;
    }

    @Override
    public Reservation getReservationById(String reservationId) {
        Reservation reservation = reservationMapper.selectById(reservationId);
        return reservation;
    }

    @Override
    public Cancellation getCancellationById(String cancellationId) {
        Cancellation cancellation = cancellationMapper.selectById(cancellationId);
        return cancellation;
    }

    @Override
    public Object cancelOrder(String orderId) {
        Order order = orderMapper.selectById(orderId);
        if(order == null){
            throw new DatabaseOperationException("该订单不存在！");
        }
        if(order.getPaymentStatus().equals("paid")){
            throw new DatabaseOperationException("该订单已支付！");
        }
        order.setPaymentStatus("expired");
        int i =  orderMapper.updateById(order);
        if(i < 1){
            throw new DatabaseOperationException("取消订单失败！");
        }
        meetingRoomService.unLockRoom(order.getRoomId());
        return "OK";
    }

    //提交取消订单表，发送审核消息给员工
    @Override
    public String submitCancelReservation(Cancellation cancellation) {
        cancellation.setId(SnowFlakeID.getSnowflakeId());
        cancellation.setStatus("requested");
        cancellation.setCreatedTime(System.currentTimeMillis());
        if(cancellation.getReservationId() == null){
            throw new DatabaseOperationException("缺少预订单id！");
        }
        QueryWrapper<Reservation> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("id",cancellation.getReservationId());
        Reservation reservation = reservationMapper.selectOne(queryWrapper);
        if(reservation == null){
            throw new DatabaseOperationException("预订单id错误，该取消表没有绑定预订单！！！");
        }
        QueryWrapper<Cancellation> queryWrapper1 = new QueryWrapper<>();
        queryWrapper1.eq("reservation_id",cancellation.getReservationId());
        long j = cancellationMapper.selectCount(queryWrapper1);
        if(j > 0){
            throw new DatabaseOperationException("重复提交取消表！！");
        }
        reservation.setStatus("refund_verifying");
        reservationMapper.updateById(reservation);
        int i = cancellationMapper.insert(cancellation);
        if(i < 1){
            throw new DatabaseOperationException("提交失败！");
        }
        MessageResult messageResult = new MessageResult(1,"cancellation",cancellation.getId());
        try {
            rabbitTemplate.convertAndSend("Front.end","staff",messageResult);
        } catch (AmqpException e) {
            throw new RuntimeException(e);
        }
        return "OK";
    }

    //员工批准取消订单表后由预订单id删除预订单

    @Override
    public Long getAllOrderCount(int paymentStatus) {
        QueryWrapper<Order> queryWrapper = new QueryWrapper<>();
        if(paymentStatus == 0){
            queryWrapper.eq("payment_status","paid");
        } else if(paymentStatus == 1){
            queryWrapper.eq("payment_status","unpaid").or().eq("payment_status","expired");
        } else {
            throw new DatabaseOperationException("请求参数不是0/1无效！");
        }
        Long i = orderMapper.selectCount(queryWrapper);
        return i;
    }

    @Override
    public List<Order> getPageOrder(int paymentStatus,PageDTO pageDTO) {
        Page<Order> page = new Page<>(pageDTO.getPage(),pageDTO.getSize());
        QueryWrapper<Order> queryWrapper =new QueryWrapper<>();
        if(paymentStatus == 0){
            queryWrapper.eq("payment_status","paid");
        } else if(paymentStatus == 1){
            queryWrapper.eq("payment_status","unpaid").or().eq("payment_status","expired");
        } else {
            throw new DatabaseOperationException("请求参数不是0/1无效！");
        }
        queryWrapper.orderByDesc("created_time");
        page = orderMapper.selectPage(page,queryWrapper);
        return page.getRecords();
    }

    @Override
    public Long getAllReservationCount(int status) {
        QueryWrapper<Reservation> queryWrapper = new QueryWrapper<>();
        if(status == 1){
            queryWrapper.eq("status","verifying");
        } else if(status == 0){
            queryWrapper.ne("status","verifying");
        } else {
            throw new DatabaseOperationException("请求参数不是0/1无效！");
        }
        Long i = reservationMapper.selectCount(queryWrapper);
        return i;
    }

    @Override
    public List<Reservation> getPageReservation(int status,PageDTO pageDTO) {
        Page<Reservation> page = new Page<>(pageDTO.getPage(),pageDTO.getSize());
        QueryWrapper<Reservation> queryWrapper =new QueryWrapper<>();
        if(status == 1){
            queryWrapper.eq("status","verifying");
        } else if(status == 0){
            queryWrapper.ne("status","verifying");
        } else {
            throw new DatabaseOperationException("请求参数不是0/1无效！");
        }
        queryWrapper.orderByDesc("created_time");
        page = reservationMapper.selectPage(page,queryWrapper);
        return page.getRecords();
    }


    @Override
    public Long getAllCancellationCount(int status) {
        QueryWrapper<Cancellation> queryWrapper = new QueryWrapper<>();
        if(status == 1){
            queryWrapper.eq("status","requested");
        } else if(status == 0){
            queryWrapper.ne("status","requested");
        } else {
            throw new DatabaseOperationException("请求参数不是0/1无效！");
        }
        Long i = cancellationMapper.selectCount(queryWrapper);
        return i;
    }

    @Override
    public List<Cancellation> getPageCancellation(int status, PageDTO pageDTO) {
        Page<Cancellation> page = new Page<>(pageDTO.getPage(),pageDTO.getSize());
        QueryWrapper<Cancellation> queryWrapper =new QueryWrapper<>();
        if(status == 1){
            queryWrapper.eq("status","requested");
        } else if(status == 0){
            queryWrapper.ne("status","requested");
        } else {
            throw new DatabaseOperationException("请求参数不是0/1无效！");
        }
        queryWrapper.orderByDesc("created_time");
        page = cancellationMapper.selectPage(page,queryWrapper);
        return page.getRecords();
    }

    @Override
    public String payOrder(String orderId) throws IllegalAccessException {
        Order order = orderMapper.selectById(orderId);
        if(order == null){
            throw new DatabaseOperationException("订单不存在！");
        }
        if(!order.getPaymentStatus().equals("unpaid")){
            throw new DatabaseOperationException("订单已支付或过期！");
        }
        order.setPaymentStatus("paid");
        order.setPaymentTime(System.currentTimeMillis());
        UpdateWrapper<Order> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("payment_status","unpaid").eq("id",order.getId());
        orderMapper.update(order,updateWrapper);
        generateReservation(order);
        meetingRoomService.unLockRoom(order.getRoomId());
        return order.getPaymentStatus();
    }

    @Override
    public Object auditCancellation(AuditCancellationDTO auditCancellationDTO) {
        String type = auditCancellationDTO.getStatus();
        Cancellation cancellation = cancellationMapper.selectById(auditCancellationDTO.getCancellationId());
        if(cancellation == null){
            throw new DatabaseOperationException("取消表单不存在！");
        }
        if(!cancellation.getStatus().equals("requested")){
            throw new DatabaseOperationException("该取消订单已经被审核！");
        }
        cancellation.setStatus(type);
        cancellation.setProcessedTime(System.currentTimeMillis());
        int i = cancellationMapper.updateById(cancellation);
        if(i < 1){
            throw new DatabaseOperationException("更新取消表单失败！");
        }
        if(type.equals("rejected")){
            AuditReservationDTO auditReservationDTO = new AuditReservationDTO(cancellation.getReservationId(),"confirmed");
            auditReservation(auditReservationDTO);
        }
        if(type.equals("approved")){
            AuditReservationDTO auditReservationDTO = new AuditReservationDTO(cancellation.getReservationId(),"refunded");
            auditReservation(auditReservationDTO);
        }
        return "OK";
    }

    @Override
    public Object auditReservation(AuditReservationDTO auditReservationDTO) {
        String type = auditReservationDTO.getStatus();
        Reservation reservation = reservationMapper.selectById(auditReservationDTO.getReservationId());
        if(reservation == null){
            throw new DatabaseOperationException("预订单不存在！");
        }
        if(!reservation.getStatus().equals("verifying") && !reservation.getStatus().equals("refund_verifying")){
            throw new DatabaseOperationException("该预订单已经被审核！");
        }
        reservation.setStatus(type);
        reservation.setProcessedTime(System.currentTimeMillis());
        Order order = orderMapper.selectById(reservation.getOrderId());
        Long time1 = order.getRequirement().getReserveDate() + order.getRequirement().getEndTime()*3600*1000;
        if(time1 < System.currentTimeMillis() && type.equals("confirmed")){
            reservation.setStatus("completed");
        }
        int i = reservationMapper.updateById(reservation);
        if(i < 1){
            throw new DatabaseOperationException("更新预订单状态失败");
        }
        return "OK";
    }


    //待发消息
    @Override
    public void generateReservation(Order order) throws IllegalAccessException {
        Reservation reservation = new Reservation(SnowFlakeID.getSnowflakeId(),order.getRoomId(),
                order.getCustomerId(),
                order.getId(), "verifying",0L,
                System.currentTimeMillis());
        if(!AllFieldsNotNull.allFieldsNotNull(reservation)){
            throw new DatabaseOperationException("有必填字段为空！！！");
        }
        int i = reservationMapper.insert(reservation);
        if(i < 1){
            throw new DatabaseOperationException("生成订单失败！");
        }
        MessageResult messageResult = new MessageResult(1,"reservation",reservation.getId());
        try {
            rabbitTemplate.convertAndSend("Front.end","staff",messageResult);
        } catch (AmqpException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public Order getUnpaidOrder(String customerId) {
        QueryWrapper<Order> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("customer_id",customerId).eq("payment_status","unpaid");
        Order order = orderMapper.selectOne(queryWrapper);
        return order;
    }

    @Override
    public List<NoticeMessage> noticeMessage() {

        List<NoticeMessage> noticeMessages = new ArrayList<>();
        int batchSize = 10;
        for (int i = 0; i < batchSize; i++) {
            MessageResult result1 = (MessageResult) rabbitTemplate.receiveAndConvert("reservation.and.cancellation");
            if (result1 == null) break; // 队列已空
            NoticeMessage noticeMessage = getNoticeMessage(result1);
            noticeMessageMapper.insert(noticeMessage);
            noticeMessages.add(noticeMessage);
        }
        return noticeMessages;
    }

    @Override
    public Object setMessageReadStatus(String id, boolean status) {
        NoticeMessage noticeMessage = noticeMessageMapper.selectById(id);
        if(noticeMessage == null){
            throw new DatabaseOperationException("消息记录不存在！");
        }
        noticeMessage.setReadStatus(status);
        noticeMessageMapper.updateById(noticeMessage);
        return "OK";
    }

    @Override
    public Object setAllMessageReadStatus(boolean status) {
        UpdateWrapper<NoticeMessage> updateWrapper = new UpdateWrapper<>();
        updateWrapper.set("read_status",status);
        noticeMessageMapper.update(null,updateWrapper);
        return "OK";
    }

    @Override
    public NoticeMessage getMessageReadStatus(String id) {
        NoticeMessage noticeMessage = noticeMessageMapper.selectById(id);
        return noticeMessage;
    }

    @Override
    public Long getAllMessageCount() {
        QueryWrapper<NoticeMessage> queryWrapper = new QueryWrapper<>();
        Long i = noticeMessageMapper.selectCount(queryWrapper);
        return i;
    }

    @Override
    public List<NoticeMessage> getPageMessage(PageDTO pageDTO) {
        Page<NoticeMessage> page = new Page<>(pageDTO.getPage(),pageDTO.getSize());
        QueryWrapper<NoticeMessage> queryWrapper =new QueryWrapper<>();
        queryWrapper.orderByDesc("created_time");
        page = noticeMessageMapper.selectPage(page,queryWrapper);
        return page.getRecords();
    }

    public NoticeMessage getNoticeMessage(MessageResult messageResult){
        if(messageResult.getType().equals("reservation")){
            return new NoticeMessage(SnowFlakeID.getSnowflakeId(),"预订单审核提醒！","要审核的条目id：" + messageResult.getDataId(),false,System.currentTimeMillis());
        } else if(messageResult.getType().equals("cancellation")){
            return new NoticeMessage(SnowFlakeID.getSnowflakeId(),"取消订单审核提醒！","要审核的条目id：" + messageResult.getDataId(),false,System.currentTimeMillis());
        }

        return null;
    }

    @Override
    public List<Order> getPageIncompleteOrder(String customerId, PageDTO pageDTO) {
        Page<Order> page = new Page<>(pageDTO.getPage(),pageDTO.getSize());
        QueryWrapper<Order> queryWrapper =new QueryWrapper<>();
        queryWrapper.eq("customer_id",customerId).ne("payment_status","paid");
        queryWrapper.orderByDesc("created_time");
        page = orderMapper.selectPage(page,queryWrapper);
        return page.getRecords();
    }

    @Override
    public List<Reservation> getPageReservationByCustomerId(String customerId, PageDTO pageDTO) {
        Page<Reservation> page = new Page<>(pageDTO.getPage(),pageDTO.getSize());
        QueryWrapper<Reservation> queryWrapper =new QueryWrapper<>();
        queryWrapper.eq("customer_id",customerId);
        queryWrapper.orderByDesc("created_time");
        page = reservationMapper.selectPage(page,queryWrapper);
        return page.getRecords();
    }

    @Override
    public Object staffDeleteReservation(String reservationId) {
        Reservation reservation = reservationMapper.selectById(reservationId);
        if(reservation == null){
            throw new DatabaseOperationException("没有这个订单id");
        }
        if(!reservation.getStatus().equals("completed")){
            throw new DatabaseOperationException("未完成预订单不能删除");
        }
        int i = 0;
        i += reservationMapper.deleteById(reservationId);
        if(reservation.getOrderId() == null){
            throw new DatabaseOperationException("这个预订单没有和任何订单绑定！");
        }
        i += orderMapper.deleteById(reservation.getOrderId());
        if(i !=2){
            throw new DatabaseOperationException("数据库错误删除失败！");
        }
        return "OK";
    }

    @Override
    public Object customerGetOrderExpired(String customerId) {
        QueryWrapper<Order> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("payment_status","expired").eq("customer_id",customerId);
        List<Order> orders = orderMapper.selectList(queryWrapper);
        return orders;
    }

    @Override
    public Object customerDeleteOrderExpired(String customerId) {
        QueryWrapper<Order> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("payment_status","expired").eq("customer_id",customerId);
        orderMapper.delete(queryWrapper);
        return "OK";
    }

    @Override
    public ReservationVO getReservationRelateDetail(String reservationId) {
        Reservation reservation = reservationMapper.selectById(reservationId);
        if(reservation == null){
            throw new DatabaseOperationException("预订单ID错误，没有这个预订单！");
        }
        Order order = orderMapper.selectById(reservation.getOrderId());
        MeetingRoom meetingRoom = meetingRoomMapper.selectById(reservation.getRoomId());
        Customer customer = (Customer) userService.getUser(reservation.getCustomerId());
        if(customer != null){
            customer.setPassword(null);
        }
        return new ReservationVO(order,customer,meetingRoom);
    }

    //    @Override
//    public Integer testRabbitMQ() {
//        String s = "hello";
//        rabbitTemplate.convertAndSend(DELAY_EXCHANGE,DELAY_ORDER_QUEUE,s);
//        return 1;
//    }
}
